#include "ThreadCache.h"
#include "CentralCache.h"
#include "PageCache.h"

// 申请空间
void* ThreadCache::Allocate(size_t size)
{
	size_t index = ClassSize::Index(size);
	size_t alignsize = ClassSize::RoundUp(size);
	if (!_freelists[index].empty())
	{
		// 从freelist中获取
		return _freelists[index].Pop();
	}

	// 从CentralCache中获取
	return FetchFromCentralCache(index, alignsize);
	
}

// 回收空间
void ThreadCache::Deallocate(void* ptr, size_t size)
{
	// size不能大于MAX_BYTES
	assert(ptr);
	assert(size <= MAX_BYTES);

	size_t index = ClassSize::Index(size);

	_freelists[index].Push(ptr);

	// 这里回收的逻辑是：如果链表内的节点个数大于一次从CentralCache申请的最大额度，就回收
	if (_freelists[index].Size() >= _freelists[index].Get_Fetch_Count())
	{
		ListTooLong(_freelists[index], size);
	}
}

// 向central池拿一个size大小的块，实际给多少由Get_Fetch_Count来决定
void* ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{
	// 范围慢启动
#ifdef WIN32
	size_t num = min(_freelists[index].Get_Fetch_Count(), ClassSize::Nummovesize(size));
#else
	size_t num = std::min(_freelists[index].Get_Fetch_Count(), ClassSize::Nummovesize(size));
#endif
	if (num == _freelists[index].Get_Fetch_Count())
		++_freelists[index].Get_Fetch_Count(); // 增长性
    // std::cout << "开始慢启动" <<  num << std::endl;
	// 拿到块的数量
	void* start = nullptr;
	void* end = nullptr;
	size_t ActuralNum = CentralCache::GetInstance()->FetchRangeBlock(start, end, num, size);
	assert(ActuralNum >= 1);

	if (ActuralNum == 1)
	{
		assert(start);
		assert(start == end);
	}
	else
	{
		assert(start && end);

		_freelists[index].PushRange(NextBlock(start), end, ActuralNum - 1);
	}

	return start;
}

// 满足size(表示空闲的块，挂在freelist下的块的个数)大于Get_Fetch_Count，就还给central池Get_Fetch_Count个块
void ThreadCache::ListTooLong(FreeList& list, size_t size)
{
	void* start = nullptr;
	void* end = nullptr;

	list.PopRange(start, end, list.Get_Fetch_Count());

	CentralCache::GetInstance()->ReleaseListToSpans(start, size);

}
